home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
pr2fl.arc
/
PR2FL.ASM
next >
Wrap
Assembly Source File
|
1985-07-13
|
7KB
|
283 lines
PAGE ,132
TITLE PR2FL - PRINTER REDIRECTION
SUBTTL By Jim Kyle - May 28, 1985 - Version 1.0
;
; This program redirects PRN output to a file. The filename is
; supplied as a pathname when the program is invoked:
;
; PR2FL C:\FILES\PRTFIL.001
;
; It achieves this goal by opening the file, saving the file's
; DCB index (the content of its handle), and then faking an entry
; in the handle table of its Program Segment Prefix to show that
; the file is closed. Next, it extracts the content of the PRN
; handle and saves it on the stack, stuffs the file's DCB index
; into the PRN handle entry, and spawns a child copy of COMMAND.COM
; to permit continued operation. While the child copy is running,
; or any program called through the child copy is executing, all
; output directed to the PRN device via standard DOS interfaces will
; go instead to the redirection file.
;
; To terminate redirection, the child copy of COMMAND.COM is
; stopped via the EXIT command. Control then returns to PR2FL.COM,
; which closes the redirection file, restores the original PRN index
; value, displays a "Redirection Ended" message, and then returns
; control to the copy of COMMAND.COM from which it was invoked.
;
; This process inherently permits nesting. Each invocation of this
; program takes away approximately 4K of RAM for the duration of
; its execution (specifically, 3920 bytes). You can nest calls of
; PR2FL as deeply as you have RAM available, and at each EXIT they
; will automatically unwind themselves.
;
; To assemble, use MASM, LINK, and EXE2BIN. If you find this
; program useful, let me know. And if you find any bugs, by all
; means tell me about them!
; Jim Kyle
; 76703,762
; SysOp, CLM SIG (GO CLM-332)
;
PAGE
;
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
ORG 0100H
START: MOV SP,OFFSET STACK ;keep the stack safe
CALL DOSVTST ;verify proper DOS version
CALL GETPATH ;set up pointers to pathname
JNZ HVPATH ;error check here if no path
MOV DX,OFFSET NOPATH
JMP SHORT FINI
HVPATH: CALL REDIR ;get file and switch
PUSH AX ;save for use at return
MOV CMDLNP+2,CS ;initialize parm block
MOV FCB1P+2,CS
MOV FCB2P+2,CS
MOV SAVSP,SP ;save stack pointer
CALL GETCOM ;set up for COMSPEC (changes DS)
CALL RELMEM ;release unneeded RAM
MOV DX,SI ;DS:DX -> Pgm to run
MOV BX,OFFSET PARMS ;ES:BX -> Parm Block
MOV AX,4B00H ;AL=0 -> Execute program
INT 21H
MOV AX,CS ;restore segments
MOV SS,AX
MOV ES,AX
MOV DS,AX
MOV SP,SAVSP ;restore stack pointer
MOV BX,4 ;PRN handle (file)
MOV AH,3EH ;close the file
INT 21H
POP AX ;restore DCB indices
MOV DI,1CH ;handle table offset for PRN in PSP
MOV [DI],AH ;restore previous PRN
MOV DX,OFFSET RTND ;return message
FINI: PUSH CS ;restore DS
POP DS
MOV AH,9 ;send message
INT 21H
INT 20H ;then get out for keeps
PAGE
;
RELMEM:
LAST = OFFSET STACK+17
MOV AX,OFFSET LAST ;release surplus memory
SHR AX,1 ;first convert to paragraphs
SHR AX,1
SHR AX,1
SHR AX,1
MOV BX,AX ;then stash in BX
MOV AX,4A00H
INT 21H
RET
;
SAVSP DW 0
;
RTND DB 13,10,'Redirection Ended',13,10,36
;
PARMS DW 0 ;env segment
CMDLNP DW OFFSET CMDLIN,0 ;new command line
FCB1P DW OFFSET FCB,0 ;new FCB1
FCB2P DW OFFSET FCB,0 ;new FCB2
;
CMDLIN DB CMDLEN ;length of command
; DB 'COMMAND /D' ;command line
CMDLEN EQU $-CMDLIN-1
DB 13 ;CR to terminate
;
FCB DB 0
DB ' '
DW 0,0
;
DB 126 DUP (?)
STACK DW 0
;
PAGE
;
; THIS CODE USED ONLY DURING SETUP, NO NEED TO KEEP IT
;
;---module dosvtst.asm
;
; verifies that DOS version is 2.0 or above, else aborts
;
dosvtst:
mov ah,30h ;version check
int 21h
xchg ah,al
cmp ax,0200h ;2.0 and above
jae vrsnok
mov dx,offset wvm
mov ah,9
int 21h
int 20h
wvm db 'DOS 2.0 or above is required',13,10,'$'
vrsnok: ret ;version is appropriate
;
;---end module dosvtst.asm
;
PAGE
;
;---module getpath.asm
;
; converts first string of command tail into ASCIIZ
; pathname for DOS use.
; destroys registers AX, CX, DX, SI, and DI
; modifies flags
;
GETPATH:
CLD
MOV SI,80H ;command tail in PSP
LODSB ;get char count
AND AL,127 ;test for no chars at all
JZ PATH5 ;none, don't scan
CBW
MOV CX,AX ;else put into CX
PATH0: MOV DX,SI ;save start offset
MOV DI,SI
LODSB ;ignore leading blank
CMP AL,' '
JA PATH2 ;non-blank, go look for end
LOOP PATH0 ;leading blank, look more
JMP SHORT PATH4 ;nothing found
;
PATH1: MOV DI,SI ;save for case fix
LODSB ;look for terminator
CMP AL,' '
JBE PATH4 ;found it
PATH2: CMP AL,'a' ;not seen, check case
JB PATH3
CMP AL,'z'
JA PATH3
AND AL,5FH ;lowercase, make upper
STOSB
PATH3: LOOP PATH1
INC DI ;to CR's location at EOS
;
PATH4: XOR AL,AL ;force a zero
MOV [DI],AL
MOV AX,DI
SUB AX,DX
PATH5: RET ;path converted
;
; Z-flag is set if no pathname was present,
; else: AX = number of characters in pathname
; CX = 0
; DX points to pathname's first character
; SI points to character past terminator (or NULL if no more)
; DI points to terminating NULL of pathname
;
;---end module getpath.asm
PAGE
;
GETCOM: MOV SI,02CH ;search Environment for COMSPEC
MOV SI,[SI]
MOV DS,SI
MOV PARMS,SI ;use parent's environment
MOV SI,0
LODSB
NXT: MOV BX,OFFSET ENVSTR
CMP AL,ES:[BX]
JNZ SKIP ;no initial match
MOV CX,7
CHK: LODSB
INC BX
CMP AL,ES:[BX]
JNZ SKIP ;failed after start
LOOP CHK
RET ;if we get here it's found
;
ENVSTR DB 'COMSPEC='
;
SKIP: LODSB ;find EOS
OR AL,AL
JNZ SKIP
LODSB ;test for end of Environment
OR AL,AL
JNZ NXT ;more to check
MOV DX,OFFSET NOENV ;hit the end!
JMP FINI
;
NOPATH DB 13,10,'Pathname is required',13,10,36
NOENV DB 13,10,'No COMSPEC= found',13,10,36
;
PAGE
;
REDIR: MOV CX,0
MOV AH,3CH ;create file
INT 21H
JC DSKERR
MOV BX,AX ;handle
MOV SI,18H ;handle table offset in PSP
MOV AL,[BX][SI] ;DCB index for new file
MOV [BX][SI],BYTE PTR 255 ;mark its handle as closed
MOV AH,[SI][4] ;DCB index for PRN handle
MOV [SI][4],AL ;set new file in as PRN
RET ;if no error (indices in AX)
;
DSKERR:
cmp ax,19
jl valerr
mov dx,offset uem
jmp short abrt
valerr: add ax,ax
mov bx,offset emt
add bx,ax
mov dx,[bx]
abrt: mov ah,9
int 21h
mov dx,offset emg2
mov ah,9
int 21h
done: int 20h
;
emg2 db '.',13,10
db 'ABORTED.',7,13,10,'$'
;
emt dw uem,em1,em2,em3,em4,em5,em6,em7
dw em8,em9,em10,em11,em12,em13,uem
dw em15,em16,em17,em18
;
uem db 'Unknown error code$'
em1 db 'Bad call$'
em2 db 'No file found$'
em3 db 'Path not found$'
em4 db 'Out of handles$'
em5 db 'Access denied$'
em6 db 'Handle bad$'
em7 db 'Memory fouled$'
em8 db 'No more RAM$'
em9 db 'Bad adr$'
em10 db 'Bad ENV$'
em11 db 'Bad format$'
em12 db 'Bad access code$'
em13 db 'Bad data$'
em15 db 'Drive not valid$'
em16 db 'Dir error$'
em17 db 'Wrong device$'
em18 db 'Out of files$'
;
CODE ENDS
END START